// js源码
/**
 * 实现merge函数类型
 * 要求sourceObj必须为targetObj的子集
 */

/*function merge1(sourceObj, targetObj) {
    const result = {...sourceObj};
    for (let key in targetObj) {
        const itemVal = sourceObj[key];
        itemVal && (result[key] = itemVal);
    }
    return result;
}

function merge2(sourceObj, targetObj) {
    return {...sourceObj, ...targetObj};
}*/


interface ISourceObj {
    x?: string;
    y?: string;
}

interface ITargetObj {
    x: string;
    y: string;
}

type IMerge2 = (sourceObj: ISourceObj, target: ITargetObj) => ITargetObj;

/**
 * 类型实现繁琐：若obj类型较为复杂，则声明source和target便需要大量重复2遍
 * 容易出错：若target增加/减少key，则需要source联动去除
 */


interface IMerge {
    <T extends Record<string, any>>(sourceObj: Partial<T>, targetObj: T): T;
}


type IPartial<T extends Record<string, any>> = {
    [P in keyof T]?: T[P];
}

//索引类型：关键字keyof，其相当于取值对象中的所有key组成的字符串字面量，如
type Ikeys = keyof { a: string; b: number }; //=>type Ikeys ="a"|"b"

//关键字in，其相当于取值字符串字面量中的一种可能，配合泛型P，即表示每个key
//关键字？，通过设定对象可选选项，即可自动推导出子集类型


